(function($, undefined) {
    var ie = !!window.ActiveXObject,
        ie6 = ie && !window.XMLHttpRequest;
    template.helper("renderValue", function(value, data, render) {
        return render ? (typeof render == "function" ? render(value, data) : render) : value;
    });
    $.fn.DataGrid = function(options) {
        return new $.fn.DataGrid.fn.init(options, this);
    };
    $.fn.DataGrid.options = function(options) {
        $.extend(this, options);
    };
    $.fn.DataGrid.options.prototype = {
        key: "id",
        clientKey: "CLIENT_ROW_ID",
        pageNo: 1,
        pageSize: 50,
        multiSelect: false
    };
    $.fn.DataGrid.fn = $.fn.DataGrid.prototype = {
        init: function(options, view) {
            var options = new $.fn.DataGrid.options(options);
            if (options == undefined) {
                throw "必须指定一个对象参数!";
            }
            if (view == undefined) {
                throw '必须在对象参数中指定view属性!';
            }
            this.options = options;
            this.view = view;
            this.dataset = new DataSet(options.sqlid);
            this._initView(options);
            this._initDataSet(options);
        },
        _initView: function(options) {
            var that = this,
                html = this.view.html(),
                hasAggr = false;
            for (var i = 0; i < options.columns.length; i++) {
                var cell = options.columns[i];
                // 检查是否需要统计和编辑
                hasAggr = hasAggr || !!cell.aggr || !!cell.aggrRender;
            };
            this.hasAggr = hasAggr;
            this.view.html(this._template(options)).addClass("nofoot");
            if (options.pageNo < 1) {
                this.view.addClass("nopage");
            }
            // 加thead的div
            this.headdiv = this.view.find(".headdiv").html(html);
            this.headdiv.find("tbody,tfoot").remove();
            // 加tbody的div
            this.bodydiv = this.view.find(".bodydiv").append(html).on("click", "tbody tr", function(event) {
                if (!$(event.target).is("input,button,select,textarea,.noselect")) {
                    if (options.multiSelect && event.shiftKey) {
                        var i1 = $(this).index(),
                            i2 = that.bodydiv.find("tr.active").index();
                        that.bodydiv.find("tbody tr").slice(Math.min(i1, i2), Math.max(i1, i2) + 1).addClass("selected");
                    } else if (options.multiSelect && event.ctrlKey) {
                        $(this).toggleClass("selected")
                    } else {
                        $(this).addClass("selected").siblings(".selected").removeClass("selected");
                    }
                    $(this).addClass("active").siblings(".active").removeClass("active");
                } else {
                    event.stopPropagation();
                }
            }).on("dblclick", "tbody td.dataeditable", function(event) {
                that._setEditEnabled($(this));
            }).on("scroll", function() {
                that.headdiv.find("table").add(that.footdiv.find("table")).css("margin-left", -$(this).scrollLeft());
            });
            if (this.bodydiv.find("tbody").length == 0) {
                this.bodydiv.find("table").append("<tbody/>");
            }
            this.bodydiv.find("tfoot").remove();
            // 加tfoot的div
            this.footdiv = this.view.find(".footdiv").html(html);
            if (this.footdiv.find("tfoot").length == 0) {
                this.footdiv.find("table").append("<tfoot/>");
            }
            this.footdiv.find("tbody").remove();
            // 加分页区的div
            this.pagediv = this.view.find(".pagediv").on("click", "a", function() {
                if ($(this).hasClass("first")) {
                    that.firstPage();
                } else if ($(this).hasClass("last")) {
                    that.lastPage();
                } else if ($(this).hasClass("next")) {
                    that.nextPage();
                } else if ($(this).hasClass("prev")) {
                    that.prevPage();
                }
            }).on("keydown", "input[name='num']", function(event) {
                if (event.keyCode == 13) {
                    var pageNo = $(this).val();
                    if (/^\d+$/.test(pageNo)) {
                        that.gotoPage(pageNo);
                    }
                    event.preventDefault();
                }
            });
            /*.on("click", "input[type='button']", function(event) {
                var pageNo = $(this).siblings("[name='num']").val();
                if (/^\d+$/.test(pageNo)) {
                    that.gotoPage(pageNo);
                }
            });*/
            this._setScrollClass();
        },
        _initDataSet: function(options) {
            var dataset = this.dataset;
            if (options.key != undefined) {
                dataset.key = options.key;
            }
            // 指定页数
            if ((options.pageNo != undefined) && (!isNaN(options.pageNo))) {
                dataset.pageNo = options.pageNo;
            }
            // 指定页码
            if ((options.pageSize != undefined) && (!isNaN(options.pageSize))) {
                dataset.pageSize = options.pageSize;
            }
            // 指定参数
            if (options.params != undefined) {
                dataset.params = options.params;
            }
            dataset.beforeOpen = $.proxy(this.beforeOpen, this);
            dataset.afterOpen = $.proxy(this.afterOpen, this);
            dataset.onInsert = $.proxy(this.onInsert, this);
            dataset.onModify = $.proxy(this.onModify, this);
            dataset.onDelete = $.proxy(this.onDelete, this);
            dataset.onError = $.proxy(this.onError, this);
        },
        beforeOpen: function() {
            this.view.addClass("dataloading").find("tbody").empty();
        },
        afterOpen: function(datas, metadatas, aggrs, response) {
            this.view.removeClass("dataloading");
            this._render(datas, metadatas, aggrs, response);
            if(response.outdata instanceof Array){
                // 获取成功
                this.view.trigger("load", [datas, metadatas, aggrs, response]);
            }else{
                // 保存成功
                this.view.trigger("update", [datas, metadatas, aggrs, response]);
            }
        },
        onInsert: function(data) {
            var options = this.options;
            this.bodydiv.find("tbody").append(this._bodyTemplate($.extend({
                view: this,
                data: [data]
            }, options)));
            this._setScrollClass();
        },
        onModify: function(data) {
            var options = this.options,
                dataset = this.dataset,
                id = data[options.key];
            this.bodydiv.find("tbody tr[data-id='" + id + "']").html($(this._bodyTemplate($.extend({
                view: this,
                data: [data]
            }, options))).html());
        },
        onDelete: function(data) {
            var options = this.options,
                dataset = this.dataset,
                id = data[options.key];
            this.bodydiv.find("tbody tr[data-id='" + id + "']").remove();
            this._setScrollClass();
        },
        onError: function() {
            this.view.removeClass("dataloading");
        },
        _render: function(datas, metadatas, aggrs, response) {
            var options = this.options;
            this.bodydiv.find("tbody").html(this._bodyTemplate($.extend({
                view: this,
                data: datas
            }, options)));
            this.pagediv.html(this._pageTemplate(this.dataset));
            if (this.hasAggr && datas.length > 0) {
                this.view.removeClass("nofoot");
                this.footdiv.find("tfoot").html(this._footTemplate($.extend({
                    data: aggrs
                }, options)));
            } else {
                this.view.addClass("nofoot");
            }
            this._setScrollClass();
        },
        /**
         * 设置滚动条对应class
         */
        _setScrollClass: function() {
            var $table = this.bodydiv.find("table"),
                vScroll = this.bodydiv.height() < this.bodydiv[0].scrollHeight,
                hScroll = this.bodydiv.width() < $table.width();
            this.view[vScroll ? "addClass" : "removeClass"]("vScroll");
            this.view[hScroll ? "addClass" : "removeClass"]("hScroll");
            // ie6 hack
            if (ie6) {
                var bottom = parseInt(this.view.find(".containerdiv").css("bottom")),
                    right = parseInt(this.view.find(".containerdiv").css("right"));
                this.view.find(".containerdiv").height(this.view.height() - bottom);
                this.bodydiv.height(this.view.height() - bottom);
                this.footdiv.add(this.headdiv).css("width", vScroll ? this.view.width - right : "");
            }
        },
        // 打开，关闭编辑模式
        _setEditEnabled: function($td) {
            var $tr = $td.parent(),
                index = $td.index(),
                options = this.options,
                dataset = this.dataset,
                data = this.getActive(),
                key = dataset.key,
                clientKey = dataset.clientKey,
                cell = options.columns[index],
                field = cell.field,
                validate = cell.edit.validate,
                editType = cell.edit.type,
                save = function(value, exInfo) {
                    var record = data;
                    record[field] = value;
                    dataset.modifyRecord(record);
                    $tr.children().eq(index).trigger("change", [value, record, exInfo]);
                },
                Editor;
            editType = editType.charAt(0).toUpperCase() + editType.substring(1);
            if ($td.siblings(".dataedit").length == 0) {
                $td.addClass("dataedit").empty();
                Editor = $.fn.DataGrid[editType + "Editor"];
                if (!Editor) {
                    Editor = $.fn.DataGrid.TextEditor;
                }
                new Editor(field, data[cell.field], data, cell.edit, $td, save);
            }
        },
        /* @group 接口 */
        // 事件绑定
        on: function() {
            $.fn.on.apply(this.view, arguments);
        },
        off: function() {
            $.fn.off.apply(this.view, arguments);
        },
        // 数据操作
        open: function(options) {
            if (options != undefined) {
                $.extned(this.dataset, options);
            }
            this.dataset.open();
        },
        close: function() {
            this.dataset.close();
        },
        firstPage: function() {
            this.dataset.firstPage();
        },
        lastPage: function() {
            this.dataset.endPage();
        },
        prevPage: function() {
            this.dataset.priorPage();
        },
        nextPage: function() {
            this.dataset.nextPage();
        },
        gotoPage: function(pageNo) {
            this.dataset.gotoPage(parseInt(pageNo));
        },
        // 获取选中项对应的数据
        getSeleted: function() {
            var dataset = this.dataset;
            return this.bodydiv.find("tr.selected").map(function() {
                return dataset.get($(this).data("id"));
            });
        },
        // 设置一行的选中状态
        setSelected: function(record, selected) {
            var id = record[this.options.key],
                $selected = this.bodydiv.find("tbody tr[data-id='" + id + "']");
            $selected[selected === false ? "removeClass" : "addClass"]("selected");
        },
        // 获取最后一个点击项对应的数据
        getActive: function() {
            var dataset = this.dataset,
                $active = this.bodydiv.find("tr.active");
            return dataset.get($active.data("id"));
        },
        // 设置一行的活跃状态
        setActive: function(record) {
            var $active = this.bodydiv.find("tbody tr[data-id='" + record[this.options.key] + "']");
            $active.addClass("active selected").siblings(".active").removeClass("active");
        },
        // 强制刷新视图，如果视图不能实时反映数据集变化
        refresh: function(){
            var dataset = this.dataset;
            this._render(dataset.datas, dataset.metadatas, dataset.aggrs, {});
        },
        // 销毁
        destroy: function() {
            this.dataset.close();
            this.view.off().empty();
        },
        /* @end 接口 */
        // html模板，依赖template.min.js
        _template: template.compile('<div class="containerdiv">\
                <div class="bodydiv"></div>\
                <div class="headdiv"></div>\
                <div class="footdiv"></div>\
            </div>\
            <div class="pagediv"></div>'),
        _bodyTemplate: template.compile('<% for (var j = 0; j < data.length; j++) {\
                var item = data[j]; %>\
                <tr data-id="<%= item[key] %>">\
                <% for (var i = 0; i < columns.length; i++) {\
                        var cell = columns[i],\
                            edit = cell.edit,\
                            value = item[cell.field],\
                            html = renderValue(value, item, cell.render); %>\
                    <td <% if(html!=null&&!/<[^>]+>/.test(html.toString())){ %>title="<%= html %>"<% } %> data-field="<%= cell.field %>" class="<%= cell.cls %> <% if(edit){ %>dataeditable<% } %>"><%=# html %></td>\
                <% } %>\
                </tr>\
            <% } %>'),
        _footTemplate: template.compile('<tr">\
            <% for (var i = 0; i < columns.length; i++) {\
                var cell = columns[i],\
                    value = data[cell.aggr],\
                    html = renderValue(value, data, cell.aggrRender); %>\
                <td class="<%= cell.cls %>"><%=# html %></td>\
            <% } %>\
            </tr>'),
        _pageTemplate: template.compile('<% if(pageNo > 0){\
            if(pageNo > 1){ %>\
                <a class="first changePage"></a>\
                <a class="prev changePage"></a>\
            <% }else{ %>\
                <span class="disabled first"></span>\
                <span class="disabled prev"></span>\
            <% } %>\
            <span class="disabled">|</span>\
            <span>\
                第 <input name="num" type="text" class="pageNo" value="<%= pageNo %>" /> /<%= pages %>页\
            </span>\
            <span class="disabled">|</span>\
            <% if(pageNo < pages){ %>\
                <a class="next changePage"></a>\
                <a class="last changePage"></a>\
            <% }else{ %>\
                <span class="disabled next"></span>\
                <span class="disabled last"></span>\
            <% } %>\
            <span class="disabled">|</span>\
            <span>每页 <%= pageSize %> 条记录/共 <%= recordcount %> 条记录</span>\
            <% } %>')
    };
    $.fn.DataGrid.fn.init.prototype = $.fn.DataGrid.fn;
    // DataGrid编辑插件
    $.fn.DataGrid.TextEditor = function(field, value, data, editOptions, $parent, save) {
        var that = this,
            view = this.view = $(this._template({
                field: field,
                value: value,
                data: data,
                editOptions: editOptions
            })).on("blur change", function(event) {
                var newValue = view.val(),
                    validate = editOptions.validate,
                    error = validate ? validate(newValue) : null;
                if (!error) {
                    save(newValue, that.getExInfo());
                } else {
                    view.next(".dataerror").remove();
                    view.after("<div class='dataerror'>" + error + "</div>")
                }
                event.stopPropagation();
            }).appendTo($parent).focus().select();
    };
    $.fn.DataGrid.TextEditor.prototype = {
        getExInfo: function() {},
        _template: template.compile('<input type="text" placeholder="<%= field %>" value="<%= value %>"/>')
    }
    $.fn.DataGrid.SelectEditor = function(field, value, editOptions, $parent, save) {
        $.fn.DataGrid.TextEditor.apply(this, arguments);
    };
    $.fn.DataGrid.SelectEditor.prototype = {
        getExInfo: function() {
            return {
                name: this.view.find(":selected").text()
            };
        },
        _template: template.compile('<select><% var datas=editOptions.datas;\
        datas = typeof datas == "function" ? datas(data) : datas;\
        for (var i = 0; i < datas.length; i++) {\
            var item=datas[i]; %>\
                 <option value="<%= item[editOptions.valueKey] %>" <% if(item[editOptions.valueKey]==value) { %>selected<% } %>><%= item[editOptions.nameKey] %></option>\
            <% } %></select>')
    }
    // 全局清除按钮
    $(document).on("click", ".clearbtn", function() {
        $(this).prev().val("").removeData();
    });
})(jQuery);